namespace GYLite
{
		
			
	/**羔羊缓动类*/
	export class GYTween
	{
		private _startTime:number;
		public delay:number;
		public updateFunc:(tween:GYTween)=>void;
		public completeFunc:(tween:GYTween)=>void;
		public startFunc:(tween:GYTween)=>void;
		public thisObject:any;
		public duration:number=0;
		public target:IResource;		
		/**缓动数组*/public tweenArr:TweenData[];
		/**动画组*/public aniArr:IAniData[];		
		private _curAniIndex:number;
		private _intervalId:number;
		private _isRunning:boolean;
		private _isReserve:boolean;
		private _completeClear:boolean;
		private _loopsCount:number;
		/**结束时准确停止再目标值上，默认false
		 * 设置此值为true则无法进行多个同属性tween的叠加，因为最终结果会被校准到最后一个tween的目标值上
		*/
		public endToTargetValue:boolean;
		public isPlayEnd:boolean;
		/**是否保持每次播放从起点值开始*/public keepFrom:boolean;
		/**循环播放次数(若要永久循环则-1或者设置一个大数字)，默认1*/
		public playLoops:number;
		
		public constructor()
		{
			var s = this;
			s._startTime=0;
			s.delay=0;
			s.updateFunc=null;
			s.completeFunc=null;
			s.startFunc=null;
			s.thisObject=null;
			s.duration=0;
			s.target=null;
			s.tweenArr=null;
			s._intervalId=-1;
			s._isRunning=false;
			s._isReserve=false;
			s._completeClear=false;
			s._curAniIndex = -1;
			s.playLoops = 1;
		}
		/**执行tween动画
		 * @param isReserve 是否翻转播放，默认false，不翻转
		 * @param aniIndex 起始的当前动画组的索引，默认-1，从头开始，即将播放0，也就是传0，则即将播放1
		 * @param reset 是否重置循环次数，默认true
		 * */
		public run(isReserve:boolean = false, aniIndex:number = -1, reset:boolean=true):void
		{var s = this;
			s.stop();			
			if(reset)
				s._loopsCount = s.playLoops;
			s.isPlayEnd = false;			
			if(s._intervalId > -1)
			{
				clearInterval(s._intervalId);				
				s._intervalId = -1;
			}
			let delay:number=null;
			if(s.aniArr)
				delay = s.aniArr[aniIndex+1].delay;
			if(delay == null)
				delay = s.delay;
			if(delay > 0)
			{				
				s._intervalId = setTimeout(s.toRun.bind(s),delay,isReserve,aniIndex);
			}				
			else
				s.toRun(isReserve, aniIndex);
		}
		/**运行tween
		 * @param isReserve 是否翻转播放
		 * @param curAniIndex 当前的动画索引，默认-1，表示从-1开始，即将播放0，也就是0，则即将播放1
		*/
		public toRun(isReserve:boolean = false, curAniIndex:number = -1):void
		{var s = this;			
			s._isReserve = isReserve;
			s._startTime = GYLite.CommonUtil.loopTime;
			s._curAniIndex = curAniIndex;
			var len:number;
			//使用了动画组
			if(s.aniArr && s.aniArr.length > 0)
			{				
				if(s.tweenArr && s.tweenArr.length > 0)				
					s.clearTweenData();
				s._curAniIndex += (s._isReserve?-1:1);				
				if(s._curAniIndex >= s.aniArr.length)
					s._curAniIndex = 0;
				else if(s._curAniIndex < 0)
					s._curAniIndex = s.aniArr.length - 1;
				s.tweenArr = TweenData.converAni(s.aniArr[s._curAniIndex], s.target);				
			}
			//缓动初始化
			len = s.tweenArr.length;
			while(--len>-1)
			{
				var data:TweenData = s.tweenArr[len];
				if(data.ease==null)data.ease = GYTween.commonEase;
				if(!s.keepFrom)
					if(isNaN(data.initFrom))data.initFrom = s.target[data.propertyName];
				if(s._isReserve)
				{
					data.from = data.initTo;
					data.to = (!s.keepFrom || data.initFrom == data.initFrom)?data.initFrom:s.target[data.propertyName];
				}
				else
				{
					data.from = (!s.keepFrom || data.initFrom == data.initFrom)?data.initFrom:s.target[data.propertyName];
					data.to = data.initTo;
				}
			}			
			if(s.startFunc!=null)s.startFunc.call(s.thisObject, s);
			if(!s._isRunning)
			{
				CommonUtil.addStageLoop(s.loop,s);
				s._isRunning = true;
				s.loop(s._startTime);				
			}						
		}
		public stop():void
		{let s = this;			
			if(s._intervalId > -1)
			{
				clearInterval(s._intervalId);				
				s._intervalId = -1;
			}
			if(!s._isRunning)return;
			s._isRunning = false;
			CommonUtil.delStageLoop(s.loop,s);
		}
		public get isRunning():boolean
		{var s = this;
			return s._isRunning;
		}
		/**当前进行的动画索引（使用多组动画连播的时候，否则默认为-1）*/
		public get curAniIndex():number
		{
			return this._curAniIndex;
		}
		private loop(t:number):void
		{var s = this;
			var len:number;
			// var compFunc:Function,sObj:any;
			if(s.target.disposed)
			{
				s.clear();
				return;
			}
			if(s.tweenArr)
			{
				len = s.tweenArr.length;
				while(--len>-1)
					s.tweenArr[len].ease(s.tweenArr[len], this);
			}			
			if(s.updateFunc!=null)s.updateFunc.call(s.thisObject,s);			
			let duration:number=null;
			if(s.aniArr)
				duration = s.aniArr[s._curAniIndex].duration;
			if(duration == null)
				duration = s.duration;
			if(CommonUtil.loopTime >= s._startTime + duration)
			{
				let isPlayEnd:boolean = true;
				//存在动画组
				if(s.aniArr && s.aniArr.length > 0)
				{					
					//动画已播放结束
					if(s._curAniIndex >= s.aniArr.length - 1 || s._isReserve && s._curAniIndex <= 0)
					{						
						--s._loopsCount;
						isPlayEnd = s._loopsCount == 0;
						if(!isPlayEnd)						
							s.run(s._isReserve,-1,false);
					}
					else
					{
						isPlayEnd = false;
						s.run(s._isReserve, s._curAniIndex);
					}						
				}
				else
				{
					--s._loopsCount;
					isPlayEnd = s._loopsCount == 0;
				}					
				s.isPlayEnd = isPlayEnd;
				if(isPlayEnd)
				{					
					if(s.completeFunc!=null)s.completeFunc.call(s.thisObject,s);
					if(s.isPlayEnd)//可能completeFunc再次启动tween，所以这里再判断一下
					{
						if(s.endToTargetValue)
						{
							let len:number;
							let tweenData:GYLite.TweenData;
							len = s.tweenArr.length;
							while(--len>-1)
							{
								tweenData = s.tweenArr[len];
								s.target[tweenData.propertyName] = tweenData.to;
							}
						}							
						if(s._completeClear)
							s.clear();
						else
						{
							s._isRunning = false;
							CommonUtil.delStageLoop(s.loop,s);
						}			
					}
							
				}
			}
		}		
		public clear(removeUse:boolean=true):void
		{var s = this;
			if(s.target == null)return;
			GYTween._pool.push(this);
			if(removeUse)
			{
				let ind:number = GYTween._useTween.indexOf(this);
				if(ind > -1)
				{
					GYTween._useTween.splice(ind, 1);
				}
			}			
			s.clearTweenData();
			s.aniArr = null;			
			s.target = null;
			s.duration = 0;
			s.delay = 0;
			s._curAniIndex = -1;
			s.playLoops = 1;
			s.completeFunc = null;
			s.startFunc = null;
			s.updateFunc = null;
			s.thisObject = null;
			s._isRunning = false;
			s._completeClear = false;
			s._isReserve = false;
			CommonUtil.delStageLoop(s.loop,s);
			if(s._intervalId > -1)
			{
				clearInterval(s._intervalId)				
				s._intervalId = -1;
			}
		}
		protected clearTweenData():void
		{
			let s = this;
			let len:number;
			len = s.tweenArr.length;
			while(--len>-1)
				(s.tweenArr[len] as TweenData).clear();			
			s.tweenArr = null;
		}
		public get startTime():number
		{var s = this;
			return s._startTime;
		}

		/**播放完成后自动清理tween*/
		public get completeClear():boolean
		{var s = this;
			return s._completeClear;
		}

		public set completeClear(value:boolean)
		{var s = this;
			s._completeClear = value;
		}

		/**是否翻转播放*/
		public get isReserve():boolean
		{var s = this;
			return s._isReserve;
		}
		/**带速度运动的缓动，tData.param 代表速度值 像素/毫秒，不填则没有初速度，是一个匀加速运动*/
		public static speedEase(tData:TweenData, t:GYTween):void
		{
			var per:number;
			var dis:number = tData.to - tData.from;			
			const T:number = tData.duration==tData.duration?tData.duration:t.duration;			
			//初速度叠加的位移
			const S:number = (tData.param?tData.param:0) * T;
			per = T==0?1:((CommonUtil.loopTime - t.startTime)/T);
			if(per > 1)			
				per = 1;
			t.target[tData.propertyName] -= tData.curVal;
			tData.curVal = (dis - S) * per * per + S * per;
			t.target[tData.propertyName] += tData.curVal;
		}
		/**匀速缓动*/
		public static commonEase(tData:TweenData,t:GYTween):void
		{
			let duration:number = tData.duration==tData.duration?tData.duration:t.duration;
			var per:number = duration==0?1:((CommonUtil.loopTime - t.startTime)/duration);			
			var dis:number = tData.to - tData.from;
			if(per > 1)
			{
				per = 1;				
			}
			
			t.target[tData.propertyName] -= tData.curVal;
			tData.curVal = dis * per;
			t.target[tData.propertyName] += tData.curVal;
		}
		/**加速缓动*/
		public static addEase(tData:TweenData,t:GYTween):void
		{
			let duration:number = tData.duration==tData.duration?tData.duration:t.duration;
			var per:number = duration==0?1:((CommonUtil.loopTime - t.startTime)/duration);			
			var dis:number = tData.to - tData.from;
			if(per > 1)
			{
				per = 1;				
			}
			
			per = per * per;			
			t.target[tData.propertyName] -= tData.curVal;
			tData.curVal = dis*per;
			t.target[tData.propertyName] += tData.curVal;
			
		}
		/**减速缓动*/
		public static reduceEase(tData:TweenData,t:GYTween):void
		{
			let duration:number = tData.duration==tData.duration?tData.duration:t.duration;
			var per:number = 1-(duration==0?1:((CommonUtil.loopTime - t.startTime)/duration));			
			var dis:number = tData.to - tData.from;
			if(per < 0)
			{
				per = 0;				
			}
			per = per * per;
			t.target[tData.propertyName] -= tData.curVal;
			tData.curVal = dis*(1 - per);
			t.target[tData.propertyName] += tData.curVal;
		}
		private static _pool:GYTween[];	
		private static _useTween:GYTween[]=[];
		/**播放一个缓动，此接口已旧，请用aniTo代替更为方便，且两个接口只能同时用一个，否则会表现异常*/
		public static to(target:any,tweenArr:Array<TweenData>,duration:number,delay:number=0,thisObject:any=null,completeFunc:(tween:GYTween)=>void=null,startFunc:(tween:GYTween)=>void=null,updateFunc:(tween:GYTween)=>void=null,runImmediate:boolean=true,isClear:boolean=true, loops:number=1):GYTween
		{
			if(!GYTween._pool)
			{				
				GYTween._pool=new Array<GYTween>();
			}			
			var t:GYTween = (GYTween._pool.length==0?new GYTween():GYTween._pool.pop());
			t.target = target;
			t.tweenArr = tweenArr;
			t.duration = duration;
			t.delay = delay;
			t.completeFunc = completeFunc;
			t.startFunc = startFunc;
			t.updateFunc = updateFunc;
			t.thisObject = thisObject;
			t.completeClear = isClear;
			t.playLoops = loops;
			GYTween._useTween.push(t);
			if(runImmediate)
				t.run();			
			return isClear?null:t;
		}

		public static aniTo(target:any,aniArr:IAniData[],duration:number,delay:number=0,thisObject:any=null,completeFunc:(tween:GYTween)=>void=null,startFunc:(tween:GYTween)=>void=null,updateFunc:(tween:GYTween)=>void=null,runImmediate:boolean=true,isClear:boolean=true, loops:number=1):GYTween
		{
			if(!GYTween._pool)
			{				
				GYTween._pool=new Array<GYTween>();
			}			
			var t:GYTween = (GYTween._pool.length==0?new GYTween():GYTween._pool.pop());
			t.target = target;
			t.aniArr = aniArr;					
			t.duration = duration;
			t.delay = delay;
			t.completeFunc = completeFunc;
			t.startFunc = startFunc;
			t.updateFunc = updateFunc;
			t.thisObject = thisObject;
			t.completeClear = isClear;
			t.playLoops = loops;
			GYTween._useTween.push(t);
			if(runImmediate)
				t.run();			
			return isClear?null:t;
		}
		/**销毁GYTween对象
		 * @param tar 操控的显示对象
		 * */
		 public static disposeByTarget(tar:any):void
		 {
			 let len:number;
			 len = GYTween._useTween.length;
			 while(--len>-1)
			 {
				 if(GYTween._useTween[len].target == tar)
				 {
					 GYTween._useTween[len].clear(false);
					 GYTween._useTween.splice(len, 1);
				 }
			 }
		 }
		
		/***对已经被销毁的对象的tween进行垃圾回收*/
		public static gc():void
		{
			let len:number;
			let tween:GYLite.GYTween;
			len = GYTween._useTween.length;
			while(--len > -1)
			{
				tween = GYTween._useTween[len];
				if(tween.target.disposed)
				{
					tween.clear(false);
					GYTween._useTween.splice(len, 1);
				}					
			}
		}
	}
}